package com.wyj.utils;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;

import com.hjq.toast.Toaster;

import org.jetbrains.annotations.NotNull;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.text.DecimalFormat;

/**
 * Created by admin on 2017/12/4.
 */

public class FileUtils {
    private static final String TAG = "FileUtils";

    /**
     * 创建文件，若文件夹不存在则自动创建文件夹，若文件存在则删除旧文件
     *
     * @param path :待创建文件路径
     */
    public static File createNewFile(String path) {
        File file = new File(path);
        try {
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            if (file.exists()) {
                file.delete();
            }
            file.createNewFile();
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
        return file;
    }

    public static boolean writeFile(ByteBuffer buffer, String path) {
        buffer.clear();
        byte[] bytes = new byte[buffer.limit()];
        buffer.get(bytes);
        return writeFile(bytes, path);
    }

    /**
     * 将文件输入流写入文件
     */
    public static boolean writeFile(byte[] bytes, String path) {
        boolean result = true;
        try {
            File file = createNewFile(path);
            FileOutputStream out = new FileOutputStream(file);
            out.write(bytes);
        } catch (Exception e) {
            result = false;
            Log.e(TAG, e.getMessage());
        }
        return result;
    }

    /**
     * 将文件输入流写入文件
     */
    public static boolean writeFile(InputStream inStream, String path) {
        boolean result = true;
        try {
            File file = createNewFile(path);
            FileOutputStream out = new FileOutputStream(file);
            byte[] data = new byte[1024];
            int num = 0;
            while ((num = inStream.read(data, 0, data.length)) != -1) {
                out.write(data, 0, num);
            }
            out.close();
        } catch (Exception e) {
            result = false;
            Log.e(TAG, e.getMessage());
        }
        return result;
    }

    /**
     * 获取文件输入流
     */
    public static InputStream readFileToInputStream(String path) {
        InputStream inputStream = null;
        try {
            File file = new File(path);
            inputStream = new FileInputStream(file);
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
        return inputStream;
    }

    /**
     * 读取文件字节数组
     */
    public static byte[] readFileToBytes(String path) {
        InputStream inputStream = readFileToInputStream(path);
        if (inputStream != null) {
            byte[] data = new byte[1024];
            ByteArrayOutputStream buffer = new ByteArrayOutputStream();
            int n = 0;
            try {
                while ((n = inputStream.read(data)) != -1) {
                    buffer.write(data, 0, n);
                }
                data = null;
                inputStream.close();
            } catch (IOException e) {
                Log.e(TAG, e.getMessage());
            }
            return buffer.toByteArray();
        }
        return null;
    }

    /**
     * 读取文件内容
     */
    public static String readFileToString(String path) {
        byte[] dataBytes = readFileToBytes(path);
        if (dataBytes != null) {
            return new String(dataBytes);
        }
        return null;
    }

    /**
     * 以行为单位读取文件，常用于读面向行的格式化文件
     */
    public static String readFileByLines(String path) {
        File file = new File(path);
        if (!file.exists() || file.isDirectory()) {
            return null;
        }
        StringBuffer buffer = new StringBuffer();
        FileReader fileReader = null;
        BufferedReader bufferedReader = null;
        try {
            fileReader = new FileReader(file);
            bufferedReader = new BufferedReader(fileReader);
            String tempString = null;
            while ((tempString = bufferedReader.readLine()) != null) {
                buffer.append(tempString).append(System.getProperty("line.separator"));
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (Exception e) {
                    Log.e(TAG, e.getMessage());
                }
            }
            if (fileReader != null) {
                try {
                    fileReader.close();
                } catch (Exception e) {
                    Log.e(TAG, e.getMessage());
                }
            }
        }
        return buffer.toString();
    }

    public static int copyStream(@NotNull InputStream in, @NotNull OutputStream out) throws IOException {
        int byteCount = 0;
        byte[] buffer = new byte[1024];
        int bytesRead = -1;
        while ((bytesRead = in.read(buffer)) != -1) {
            out.write(buffer, 0, bytesRead);
            byteCount += bytesRead;
        }
        out.flush();
        return byteCount;
    }

    public static void copyFile(@NotNull Context context, @NotNull Uri srcUri, @NotNull String dstPath) {
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
            if (inputStream == null) return;
            File dstFile = createNewFile(dstPath);
            OutputStream outputStream = new FileOutputStream(dstFile);
            copyStream(inputStream, outputStream);
            inputStream.close();
            outputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据给出路径自动选择复制文件或整个文件夹
     *
     * @param src  :源文件或文件夹路径
     * @param dest :目标文件或文件夹路径
     */
    public static void copyFiles(String src, String dest) {
        File srcFile = new File(src);
        if (srcFile.exists()) {
            if (srcFile.isFile()) {
                writeFile(readFileToInputStream(src), dest);
            } else {
                File[] subFiles = srcFile.listFiles();
                if (subFiles.length == 0) {
                    File subDir = new File(dest);
                    subDir.mkdirs();
                } else {
                    for (File subFile : subFiles) {
                        String subDirPath = dest + System.getProperty("file.separator") + subFile.getName();
                        copyFiles(subFile.getAbsolutePath(), subDirPath);
                    }
                }
            }
        }
    }

    /**
     * 根据给出路径自动选择删除文件或整个文件夹
     *
     * @param path :文件或文件夹路径
     */
    public static void deleteFiles(String path) {
        deleteFiles(new File(path));
    }

    /**
     * 根据给出路径自动选择删除文件或整个文件夹
     *
     * @param file :文件或文件夹
     */
    public static void deleteFiles(File file) {
        if (file == null || !file.exists()) {
            return;
        }
        // 删除当前目录
        if (!file.isFile()) {
            File[] subFiles = file.listFiles();
            for (File subfile : subFiles) {
                deleteFiles(subfile.getAbsolutePath());// 删除当前目录下的子目录
            }
        }
        file.delete();// 删除文件
    }

    /**
     * 将图片保存为文件
     */
    public static void saveBitmapToFile(Bitmap bitmap, String path) {
        if (null == bitmap || null == path || 0 == path.trim().length()) {
            return;
        }
        File file = createNewFile(path);
        try {
            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(CompressFormat.JPEG, 85, out);
            out.flush();
            out.close();
        } catch (IOException e) {
            Log.e(TAG, e.getMessage());
        }
    }

    public static final boolean writeFileFromString(String path, String fileName, String result) {
        try {
            File dir = new File(path);
            if (!dir.exists())
                dir.mkdirs();
            return writeFileFromString(path + "/" + fileName, result);
        } catch (Exception e) {
            return false;
        }
    }

    public static final boolean writeFileFromString(String fileName, String result) {
        try {
            createNewFile(fileName);
            FileOutputStream os = new FileOutputStream(new File(fileName));
            os.write(result.getBytes());
            os.close();
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static final boolean appendFileFromString(String path, String fileName, String content) {
        try {
            File dir = new File(path);
            if (!dir.exists())
                dir.mkdirs();
            return appendFileFromString(path + "/" + fileName, content);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public static final boolean appendFileFromString(String fileName, String content) {
        try {
            File file = new File(fileName);
            // 打开一个写文件器，构造函数中的第二个参数true表示以追加形式写文件
            FileWriter writer = new FileWriter(file, true);
            writer.write(content);
            writer.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据文件地址解析bitmap，OOM时对bitmap进行压缩输出(压缩至1/4或者1/16)
     *
     * @param path :文件地址
     */
    public static Bitmap getBitmapFromFile(String path) {
        Bitmap bitmap = null;
        if (null == path || 0 == path.trim().length()) {
            return bitmap;
        }
        File file = new File(path);
        if (file.exists()) {
            try {
                bitmap = BitmapFactory.decodeFile(path, null);
            } catch (OutOfMemoryError e) {
                BitmapFactory.Options options = new BitmapFactory.Options();
                try {
                    System.gc();
                    options.inSampleSize = 2;
                    bitmap = BitmapFactory.decodeFile(path, options);
                } catch (OutOfMemoryError e1) {
                    try {
                        System.gc();
                        options.inSampleSize = 4;
                        bitmap = BitmapFactory.decodeFile(path, options);
                    } catch (OutOfMemoryError e2) {
                        System.gc();
                        Log.e(TAG, e2.getMessage());
                    }
                }
            }
        }
        return bitmap;
    }

    /**
     * 转换文件大小
     */
    public static String FormetFileSize(long size) {//转换文件大小
        DecimalFormat df = new DecimalFormat("#.00");
        String result = "";
        if (size < 1024) {
            result = df.format((double) size) + "B";
        } else if (size < 1048576) {
            result = df.format((double) size / 1024) + "K";
        } else if (size < 1073741824) {
            result = df.format((double) size / 1048576) + "M";
        } else {
            result = df.format((double) size / 1073741824) + "G";
        }
        return result;
    }

    public static String getMD5(File file) {
        if (!file.isFile()) {
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            in = new FileInputStream(file);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16);
    }

    //保存图片
    public static void scanFile(Context context, File file) {
        String mimeType = getMimeType(file);
        if (SdkVersionUtils.isAndroid10()) {
            String fileName = file.getName();
            ContentValues values = new ContentValues();
            values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName);
            values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType);
            values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
            ContentResolver contentResolver = context.getContentResolver();
            Uri uri = contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
            if (uri == null) {
                Toaster.show("图片保存失败");
                return;
            }
            try {
                OutputStream out = contentResolver.openOutputStream(uri);
                FileInputStream fis = new FileInputStream(file);
                copyStream(fis, out);
                fis.close();
                out.close();
                Toaster.show("图片已成功保存到相册");
            } catch (Exception e) {
                Toaster.show("图片保存失败");
            }
        } else {
            MediaScannerConnection.scanFile(context, new String[]{file.getPath()}, new String[]{mimeType}, (path, uri) -> {
                Toaster.show("图片已成功保存到" + path);
            });
        }
    }


    public static String getMimeType(File file) {
        FileNameMap fileNameMap = URLConnection.getFileNameMap();
        String type = fileNameMap.getContentTypeFor(file.getName());
        return type;
    }
}
